﻿using CharacterCreation.Data.Models;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Controls;

namespace CharacterCreation.Data.Services {
    /// <summary>
    /// Delegates the creation, updating and deleting of the characters in the database.
    /// </summary>
    public class CharacterService : BaseService<Character, CharacterService> {


        public override Character CreateNewItem() {
            Character character = new Character() {
                Strength = new CharacterStatistic<Strength>(),
                Dexterity = new CharacterStatistic<Dexterity>(),
                Fighting = new CharacterStatistic<Fighting>(),
                Constitution = new CharacterStatistic<Constitution>(),
                Perception = new CharacterStatistic<Perception>(),
                Intelligence = new CharacterStatistic<Intelligence>(),
                WillPower = new CharacterStatistic<WillPower>(),
                Charisma = new CharacterStatistic<Charisma>(),
                HitPoints = new CharacterStatistic<HitPoints>(),
                Essence = new CharacterStatistic<Essence>(),

                Name = "new character",
                Edge = 3,

                Skills = new System.Collections.ObjectModel.ObservableCollection<CharacterSkill>(),
                Specials = new System.Collections.ObjectModel.ObservableCollection<CharacterSpecial>()
            };

            character.Register();
            return character;
        }

        public override void DeleteCurrentItem() {

            var temp = this.CurrentItem;

            this.Items.Remove(temp);

            DataContext.Delete(this.CurrentItem.Strength);
            DataContext.Delete(this.CurrentItem.Dexterity);
            DataContext.Delete(this.CurrentItem.Fighting);
            DataContext.Delete(this.CurrentItem.Constitution);
            DataContext.Delete(this.CurrentItem.Perception);
            DataContext.Delete(this.CurrentItem.Intelligence);
            DataContext.Delete(this.CurrentItem.WillPower);
            DataContext.Delete(this.CurrentItem.Charisma);
            DataContext.Delete(this.CurrentItem.HitPoints);
            DataContext.Delete(this.CurrentItem.Essence);

            foreach (var characterSkill in this.CurrentItem.Skills)
                DataContext.Delete(characterSkill);

            foreach (var characterSpecial in this.CurrentItem.Specials)
                DataContext.Delete(characterSpecial);
            
            DataContext.Delete(this.CurrentItem);

            this.CurrentItem = null;
        }

        /// <summary>
        /// Creates the character documetn
        /// </summary>
        public FlowDocument Document {
            get {
                if (this.CurrentItem != null) {
                    FlowDocument flowDocument = new FlowDocument();
                    flowDocument.Blocks.Add(headerBlock());
                    flowDocument.Blocks.Add(xpBlock());
                    flowDocument.Blocks.Add(statisticsBlock());
                    flowDocument.Blocks.Add(skillBlock());
                    flowDocument.Blocks.Add(specialBlock());
                    return flowDocument;
                }
                else {
                    return new FlowDocument();
                }
            }
        }

        private Paragraph headerBlock() {
            Run title = new Run(this.CurrentItem.Name);
            title.FontSize = 26d;
            title.FontWeight = System.Windows.FontWeights.Bold;
            title.Foreground = new SolidColorBrush(Colors.Maroon);

            Run age = new Run(string.Format("\r\nAge: {0}", this.CurrentItem.Age));
            Run alignment = new Run(string.Format("\r\nAlignment: {0}", this.CurrentItem.Alignment));
            Run edge = new Run(string.Format("\r\nEdge: {0}", this.CurrentItem.Edge));
            Run description = new Run(string.Format("\r\nDescription:\r\n {0}", this.CurrentItem.Description));

            Paragraph detailsP = new Paragraph();
            detailsP.Inlines.Add(title);
            detailsP.Inlines.Add(age);
            detailsP.Inlines.Add(alignment);
            detailsP.Inlines.Add(edge);
            detailsP.Inlines.Add(description);
            return detailsP;
        }

        private Paragraph statisticsBlock() {
            Paragraph p = new Paragraph();
            Run xpTitle = new Run("Statistics\r\n");
            xpTitle.FontSize = 15d;
            xpTitle.Foreground = new SolidColorBrush(Colors.Maroon);
            xpTitle.FontWeight = System.Windows.FontWeights.Bold;
            p.Inlines.Add(xpTitle);

            Run strengthRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3} \r\n", this.CurrentItem.Strength.TotalXP,
                "Strength:", this.CurrentItem.Strength.Score, this.CurrentItem.Strength.Statistic.ToString()));
            p.Inlines.Add(strengthRun);
            Run dexRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3} \r\n", this.CurrentItem.Dexterity.TotalXP,
                "Dexterity:", this.CurrentItem.Dexterity.Score, this.CurrentItem.Dexterity.Statistic));
            p.Inlines.Add(dexRun);
            Run figRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.Fighting.TotalXP,
                "Fighting:", this.CurrentItem.Fighting.Score, this.CurrentItem.Fighting.Statistic));
            p.Inlines.Add(figRun);
            Run conRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.Constitution.TotalXP,
                "Constitution:", this.CurrentItem.Constitution.Score, this.CurrentItem.Constitution.Statistic));
            p.Inlines.Add(conRun);
            Run perRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.Perception.TotalXP,
                "Perception:", this.CurrentItem.Perception.Score, this.CurrentItem.Perception.Statistic));
            p.Inlines.Add(perRun);
            Run intRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.Intelligence.TotalXP,
                "Intelligence:", this.CurrentItem.Intelligence.Score, this.CurrentItem.Intelligence.Statistic));
            p.Inlines.Add(intRun);
            Run willRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.WillPower.TotalXP,
               "Willpower:", this.CurrentItem.WillPower.Score, this.CurrentItem.WillPower.Statistic));
            p.Inlines.Add(willRun);
            Run chaRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.Charisma.TotalXP,
               "Charisma:", this.CurrentItem.Charisma.Score, this.CurrentItem.Charisma.Statistic));
            p.Inlines.Add(chaRun);
            Run hpRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}\r\n", this.CurrentItem.HitPoints.TotalXP,
               "Hitpoints:", this.CurrentItem.HitPoints.Score, this.CurrentItem.HitPoints.Statistic));
            p.Inlines.Add(hpRun);
            Run essRun = new Run(string.Format("XP: {0} -> {1} -> {2} {3}", this.CurrentItem.Essence.TotalXP,
               "Essence:", this.CurrentItem.Essence.Score, this.CurrentItem.Essence.Statistic));
            p.Inlines.Add(essRun);

            return p;
        }

        private Paragraph xpBlock() {
            Paragraph p = new Paragraph();
            Run xpTitle = new Run("XP");
            xpTitle.FontSize = 15d;
            xpTitle.Foreground = new SolidColorBrush(Colors.Maroon);
            xpTitle.FontWeight = System.Windows.FontWeights.Bold;
            p.Inlines.Add(xpTitle);

            Run xp = new Run(string.Format("\r\nRacial XP: {0}, Professional XP: {1}, Miscellaneous XP: {2}, XP: {3}", 
                this.CurrentItem.TotalRacialXP, this.CurrentItem.TotalProfessionalXP, this.CurrentItem.TotalMiscellaneousXP, this.CurrentItem.TotalXP));

            p.Inlines.Add(xp);
            return p;
        }

        private Paragraph skillBlock() {
            Paragraph p = new Paragraph();
            Run skillstitle = new Run("Skills\r\n");
            skillstitle.FontSize = 15d;
            skillstitle.Foreground = new SolidColorBrush(Colors.Maroon);
            skillstitle.FontWeight = System.Windows.FontWeights.Bold;
            p.Inlines.Add(skillstitle);
            foreach (CharacterSkill skill in this.CurrentItem.Skills) {
                if (skill.Score < 1) skill.CalculateSkillLevel(this.CurrentItem);
                Run skillRun = new Run(string.Format("XP: {0} -> {1} -> {2} \r\n", skill.TotalXP, skill.Skill.Name, skill.Score));
                p.Inlines.Add(skillRun);
            }
            //skillsP.Inlines.Add(new Run("\r\n"));
            return p;
        }

        private Paragraph specialBlock() {
            Paragraph p = new Paragraph();
            Run specialstitle = new Run("Specials\r\n");
            specialstitle.FontSize = 15d;
            specialstitle.Foreground = new SolidColorBrush(Colors.Maroon);
            specialstitle.FontWeight = System.Windows.FontWeights.Bold;
            p.Inlines.Add(specialstitle);

            foreach (CharacterSpecial special in this.CurrentItem.Specials) {
                if (special.Score < 1) special.CalculateSpecialLevel(this.CurrentItem);
                Run skillRun = new Run(string.Format("XP: {0} -> {1} -> {2} \r\n", special.TotalXP, special.Special.Name, special.Score));
                p.Inlines.Add(skillRun);
            }
           // specialsP.Inlines.Add(new Run("\r\n"));
            return p;
        }

        public override void OnCurrentItemChanged() {
            RaisePropertyChanged("Document");
        }

        public override void Export() {
            FlowDocument character = this.Document;
            FlowDocumentPageViewer fdpv = new FlowDocumentPageViewer();
            fdpv.Document = character;
            fdpv.Print();
        }
        
    }
}
